﻿namespace VisualPhysics.Scene.Core.Tests

open System
open VisualPhysics.Scene.Core
open VisualPhysics.Scene.Core.Operators
open VisualPhysics.Scene.Core.Tests.Utils
open NUnit.Framework
open FsUnit

type [<TestFixture>] ``Operators tests``() =
    
    [<Test>]
    [<Category("Ops.point")>]
    member t.``Converting 0, 0 to a PointF``() =
        let pointf = point (0, 0)
        (pointf.X, pointf.Y) |> should equal (0.0f, 0.0f)

    [<Test>]
    [<Category("Ops.point")>]
    member t.``Converting 15, 40 to a PointF``() =
        let pointf = point (15.0, 40.0)
        (pointf.X, pointf.Y) |> should equal (15.0f, 40.0f)

    [<Test>]
    [<Category("Ops.deg2rad")>]
    member t.``Converting 0o to radians``() =
        let result = deg2rad 0.0<degree>
        result |> should equal 0.0

    [<Test>]
    [<Category("Ops.deg2rad")>]
    member t.``Converting 180o to radians``() =
        let result = deg2rad 180.0<degree>
        result |> should equal Math.PI

    [<Test>]
    [<Category("Ops.deg2rad")>]
    member t.``Converting 45o to radians``() =
        let result = deg2rad 45.0<degree>
        result |> should equal (Math.PI / 4.0)

    [<Test>]
    [<Category("Ops.rad2deg")>]
    member t.``Converting 0 to degrees``() =
        let result = rad2deg 0.0
        result |> should equal 0.0<degree>

    [<Test>]
    [<Category("Ops.rad2deg")>]
    member t.``Converting Pi to degrees``() =
        let result = rad2deg Math.PI
        result |> should equal 180.0<degree>

    [<Test>]
    [<Category("Ops.rad2deg")>]
    member t.``Converting Pi/4 to degrees``() =
        let result = rad2deg (Math.PI / 4.0)
        result |> should equal 45.0<degree>

    [<Test>]
    [<Category("Ops.distance")>]
    member t.``Distance between (10, 10) and (15, 15)``() =
        let result = distance (10.0, 10.0) (15.0, 15.0)
        result |> should equal (sqrt 50.0)

    [<Test>]
    [<Category("Ops.distance")>]
    member t.``Distance between (10, 10) and (15, 20)``() =
        let result = distance (10.0, 10.0) (15.0, 20.0)
        result |> should equal (sqrt 125.0)

    [<Test>]
    [<Category("Ops.rotate")>]
    member t.``Rotate (0, 1) by Pi``() =
        let result = rotate (0.0, 1.0) Math.PI
        result
        |> equalTuples (0.0, -1.0)
        |> should equal (0.0, -1.0)

    [<Test>]
    [<Category("Ops.rotate")>]
    member t.``Rotate (0, 1) by Pi/2``() =
        let result = rotate (0.0, 1.0) (Math.PI / 2.0)
        result
        |> equalTuples (-1.0, 0.0)
        |> should equal (-1.0, 0.0)

    [<Test>]
    [<Category("Ops.rotate")>]
    member t.``Rotate (1, 0) by Pi/4``() =
        let result = rotate (1.0, 0.0) (Math.PI / 4.0)
        let sqrt2Div2 = sqrt 2.0 / 2.0
        result
        |> equalTuples (sqrt2Div2, sqrt2Div2)
        |> should equal (sqrt2Div2, sqrt2Div2)

    [<Test>]
    [<Category("Ops.ValueOnly")>]
    member t.``ValueOnly of Some 3``() =
        let option = Some 3
        let internalTest (ValueOnly(v)) =
            v
        internalTest option |> should equal 3

    [<Test>]
    [<Category("Ops.ValueOnly")>]
    member t.``ValueOnly of None``() =
        let option = None
        let internalTest (ValueOnly(v)) =
            v
        (fun () -> internalTest option |> ignore) |> should throw typeof<ArgumentException>

    [<Test>]
    [<Category("Ops.Pol")>]
    member t.``Pol of (1, 1)``() =
        let result = pol (1.0, 1.0)
        result |> should equal (sqrt 2.0, Math.PI / 4.0)

    [<Test>]
    [<Category("Ops.Pol")>]
    member t.``Pol of (-1, 0)``() =
        let result = pol (-1.0, 0.0)
        result |> should equal (-1.0, 0.0)

    [<Test>]
    [<Category("Ops.Car")>]
    member t.``Car of (Sqrt(2), Pi/4)``() =
        let result = car (sqrt 2.0, Math.PI / 4.0)
        result
        |> equalTuples (1.0, 1.0)
        |> should equal (1.0, 1.0)